/********************************************************************

Base exception class and related precompile defines
HOWTO: You can custom child exceptions and override getReason() function. 
For exceptions of OOPException and all its descendants, USE OOPTHROW or 
OOPTHROW_A to throw them, and the catch type is corresponding reference
type (or its ancestor). 
OOPTHROW is for simple exception type which does not need to be set 
additional information before thrown. The only parameter is the type of 
the exception to throw. It will use default constructor to construct an 
exception object of the type specified and throw it.
OPPTHROW_A is for complex exception type. The first parameter is the 
exception object and the second one is its type. 

Write Date: 2011/03/23
Author: Deng Nianchen
>>>> Implements an exception framework. Defines the base exception class

*********************************************************************/
#ifndef OOP_EXCEPTION_HPP
#define OOP_EXCEPTION_HPP
#include "Global.hpp"
#include <string>
#include <sstream>



#define OOPTHROW(__type__) { __type__ __e__; OOPUtils::OOPException::setDebugInfo (__e__, __FILE__, __FUNCTION__, __LINE__); throw __e__; }

#define OOPTHROW_A(__obj__, __type__) { __type__ & __e__ = __obj__; OOPUtils::OOPException::setDebugInfo (__e__, __FILE__, __FUNCTION__, __LINE__); throw __e__; }




_OOPUTILS_BEGIN




using namespace std;




/**************************************************************************************************
 * <summary>  Exception for signalling oop errors.  </summary>
 *
 * <remarks>  Deng Nianchen, 2011/3/22. </remarks>
 **************************************************************************************************/

class OOPException
{

private:

  string _fileName;
  string _functionName;
  uint _lineNumber;

public:

  OOPException () throw () : _lineNumber () {}

  virtual ~OOPException () throw () {}

  /**************************************************************************************************
   * <summary>  Get the file name of the file which contains related throw 
   * 						statement. </summary>
   *
   * <remarks>  Deng Nianchen, 2011/3/22. </remarks>
   *
   * <returns>  The file name. </returns>
   **************************************************************************************************/

  string getFileName () const throw () { return _fileName; }

  /**************************************************************************************************
   * <summary>  Set the name of the file which contains related throw 
   * 						statement. </summary>
   *
   * <remarks>  Deng Nianchen, 2011/3/22. </remarks>
   *
   * <param name="fileName">  Filename of the file. </param>
   **************************************************************************************************/

  void setFileName (const string & fileName) throw () { _fileName = fileName; }

  /**************************************************************************************************
   * <summary>  Get the name of the function which contains related throw 
   * 						statement. </summary>
   *
   * <remarks>  Deng Nianchen, 2011/3/22. </remarks>
   *
   * <returns>  The function name. </returns>
   **************************************************************************************************/

  string getFunctionName () const throw () { return _functionName; }

  /**************************************************************************************************
   * <summary>  Set the name of the function which contains related throw 
   * 						statement. </summary>
   *
   * <remarks>  Deng Nianchen, 2011/3/22. </remarks>
   *
   * <param name="funcName">  Name of the function. </param>
   **************************************************************************************************/

  void setFunctionName (const string & funcName) throw () { _functionName = funcName; }

  /**************************************************************************************************
   * <summary>  Get the line number of related throw statement. </summary>
   *
   * <remarks>  Deng Nianchen, 2011/3/22. </remarks>
   *
   * <returns>  The line number. </returns>
   **************************************************************************************************/

  uint getLineNumber () const throw () { return _lineNumber; }

  /**************************************************************************************************
   * <summary>  Set line number of related throw statement. </summary>
   *
   * <remarks>  Deng Nianchen, 2011/3/22. </remarks>
   *
   * <param name="lineNumber">  The line number. </param>
   **************************************************************************************************/

  void setLineNumber (uint lineNumber)  throw () { _lineNumber = lineNumber; }

  /**************************************************************************************************
   * <summary>  Get the full description of the exception. That includes 
   * 						exception class name, file, function and line number of 
   * 						the related throw statement and the reason. </summary>
   *
   * <remarks>  Deng Nianchen, 2011/3/22. </remarks>
   *
   * <returns>  The full description of the exception. </returns>
   **************************************************************************************************/

  virtual wstring getDescription () const throw ()
  {
    wostringstream wsOut;
    wsOut << typeid (*this).name () << " at " << _functionName.c_str ()
      << " (" << _fileName.c_str () << ":" << _lineNumber << "): "
      << getReason ();
    return wsOut.str ();
  }

  /**************************************************************************************************
   * <summary>  Get the reason of the exception. This function can be 
   * 						overrode in custom exception classes to return custom 
   * 						information </summary>
   *
   * <remarks>  Deng Nianchen, 2011/3/22. </remarks>
   *
   * <returns>  the reason of the exception. </returns>
   **************************************************************************************************/

  virtual wstring getReason () const throw ()
  {
    return L"Unknown exception.";
  }

  /**************************************************************************************************
   * <summary>  Sets debug information such as file, function and line 
   * 						of related throw statement. </summary>
   *
   * <remarks>  Deng Nianchen, 2011/3/23. </remarks>
   *
   * <param name="e">     [in,out] The exception to set debug info to. </param>
   * <param name="file">  The file. </param>
   * <param name="func">  The function. </param>
   * <param name="line">  The line. </param>
   **************************************************************************************************/

  static void setDebugInfo (OOPException & e, const char * file,
    const char * func, int line)
  {
    e.setFileName (file);
    e.setFunctionName (func);
    e.setLineNumber (line);
  }

}; // End of class OOPException

_OOPUTILS_END

#endif